﻿#if ANDROID
using Android.Content;
#endif
using System.Collections.ObjectModel;
using System.Text;
using AnyTap.Models;
using AnyTap.Services;
using CommunityToolkit.Maui.Alerts;
using CommunityToolkit.Maui.Core;
using CommunityToolkit.Maui.Storage;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using static AnyTap.Services.Helper;
using CommunityToolkit.Maui.Views;
using AnyTap.Views;
namespace AnyTap.ViewModels;

public partial class MainViewModel : BaseViewModel
{
	#region 定义
	#region 命令
	[RelayCommand]
	private static void Stop()
	{ }

	[RelayCommand]
	private static void Start()
	{
#if ANDROID
		Platform.CurrentActivity.MoveTaskToBack(true);
		if(!OperatingSystem.IsAndroidVersionAtLeast(23) || Android.Provider.Settings.CanDrawOverlays(Android.App.Application.Context))
		{
			Android.App.Application.Context.StartService(new Intent(Android.App.Application.Context, typeof(BallService)));
		}
#endif
	}

	[RelayCommand]
	private static void Capture()
	{ }

	[RelayCommand]
	private static void AccessibilityService()
	{
#if ANDROID
		Android.App.Application.Context.StartActivity(new Intent(Android.Provider.Settings.ActionAccessibilitySettings).AddFlags(ActivityFlags.NewTask));
#endif
	}
	#endregion

	#region 档案
	public string SelectedDoc => Settings?.LatestDocName;

	public Doc DocFile => Helper.Doc;

	[ObservableProperty]
	private ItemViewModel selectedItem;

	[ObservableProperty]
	private ObservableCollection<ItemViewModel> itemList = [];

	[RelayCommand]
	private async Task Open()
	{
		if(await Shell.Current?.DisplayActionSheet("打开脚本", null, null, Directory.GetFiles(DIR_DOC, $"*{EXT_DOC}").Select(Path.GetFileNameWithoutExtension).ToArray()) is string doc
			&& !string.Equals(doc, Settings?.LatestDocName))
		{
			LoadDoc(doc);
		}
	}

	#region 命令
	[RelayCommand]
	private void NewDoc() => NewDoc(name =>
	{
		SaveDocFile(name, null);
		LoadDoc(name);
	});

	/// <summary>
	/// 保存档案
	/// </summary>
	[RelayCommand]
	private static void SaveDoc()
	{
		SaveDocFile();
		Toast.Make("脚本已保存").Show();
	}

	[RelayCommand]
	private void SaveasDoc()
	{
		if(SelectedDoc == null)
			return;

		NewDoc(name =>
		{
			SaveDocFile(name);
			LoadDoc(name);
		});
	}

	[RelayCommand]
	private async Task DelDoc()
	{
		if(SelectedDoc == null)
			return;

		if(await Shell.Current?.DisplayAlert("提示", "确定删除此脚本吗?", "OK", "Cancel"))
		{
			DelDocFile(SelectedDoc);
			LoadDoc(null);
		}
	}

	static readonly string[] EXT_Win = [EXT_DOC];
	static readonly string[] EXT_Android = ["*/*"];
	static readonly PickOptions opt = new()
	{
		PickerTitle = "导入脚本",
		FileTypes = new(new Dictionary<DevicePlatform, IEnumerable<string>>
		{
			{ DevicePlatform.WinUI, EXT_Win }, // file extension
			{ DevicePlatform.Android, EXT_Android}, // MIME type. Android暂不支持指定Json类型
		})
	};

	[RelayCommand]
	private static async Task Import()
	{
		var files = await FilePicker.PickMultipleAsync(opt);
		if(files?.Count() > 0)
		{
			foreach(var result in files)
			{
				using var stream = await result.OpenReadAsync();
				using var outputStream = File.Create(Path.Combine(DIR_DOC, result.FileName));
				await stream.CopyToAsync(outputStream);
			}

			Toast.Make($"导入完成");
		}
	}

	[RelayCommand]
	private async Task Export()
	{
		if(SelectedDoc == null)
			return;

		using var stream = new MemoryStream(Encoding.Default.GetBytes(DocFile.WriteObject()));
		var fileSaverResult = await FileSaver.Default.SaveAsync($"{SelectedDoc}{EXT_DOC}", stream, CancellationToken.None);
		if(fileSaverResult.IsSuccessful)
		{
			await Toast.Make($"保存成功: {fileSaverResult.FilePath}").Show(CancellationToken.None);
		}
		else
		{
			await Toast.Make($"保存错误: {fileSaverResult.Exception.Message}", ToastDuration.Long).Show(CancellationToken.None);
		}
	}

	[RelayCommand] private void MoveUp() => MoveItem(true);
	[RelayCommand] private void MoveDown() => MoveItem(false);

	[RelayCommand]
	private void Add() => AddItem(new(GestureType.Click, 0, 0, 0, true, 100));

	[RelayCommand]
	private void Copy()
	{
		if(SelectedItem is null)
			return;

		AddItem(SelectedItem.Core.Clone());
	}

	[RelayCommand] private void Delete() => DeleteItem();
	#endregion
	#endregion
	#endregion

	public MainViewModel()
	{
		#region 文件夹
		Directory.CreateDirectory(DIR_LOG);
		Directory.CreateDirectory(DIR_SYS);
		Directory.CreateDirectory(DIR_DOC);
		Directory.CreateDirectory(DIR_DATA);
		#endregion
	}

	public override async Task OnAppearing()
	{
		Settings = ReadObject<Setting>(FILE_SETTING) ?? new();
		if(!Settings.Agree)
		{
			await Shell.Current.ShowPopupAsync(new AuthPopup());
		}

		Settings.Agree = true;
		Settings.UNIID ??= GetDeviceID();
		Settings.WriteObject(FILE_SETTING);

		LoadDoc(Settings.LatestDocName);
	}

	protected virtual void LoadDoc(string doc)
	{
		SelectedItem = null;
		LoadDocFile(doc);
		OnPropertyChanged(nameof(DocFile));
		OnPropertyChanged(nameof(SelectedDoc));
		if(Helper.Doc?.Items == null)
		{
			ItemList.Clear();
		}
		else
		{
			Helper.Doc.Reset();
			var items = new List<ItemViewModel>();
			foreach(var item in Helper.Doc.Items)
			{
				items.Add(new ItemViewModel(item));
			}

			ItemList = new(items);
		}
	}

	/// <summary>
	/// 新建测试档案
	/// </summary>
	private static async void NewDoc(Action<string> action)
	{
		var name = await Shell.Current?.DisplayPromptAsync("请输入名称", null, maxLength: 64, keyboard: Keyboard.Text);
		if(string.IsNullOrWhiteSpace(name))
			return;

		const string ILLEGAL_CHAR = " \\/*?:\"<>|";
		if(name.Any(ILLEGAL_CHAR.Contains))
		{
			await Shell.Current?.DisplayAlert("提示", $"请勿使用非法字符\n{ILLEGAL_CHAR}", "OK");
			return;
		}

		if(!IsDocExists(name)
			|| await Shell.Current?.DisplayAlert("提示", $"{name}已存在,是否覆盖文件?", "Yes", "No"))
		{
			action?.Invoke(name);
		}
	}

	/// <summary>
	/// 创建测试项
	/// </summary>
	private void AddItem(TapGesture item)
	{
		if(Helper.Doc == null)
			return;

		int index = SelectedItem == null ? ItemList.Count : ItemList.IndexOf(SelectedItem) + 1;
		var view = new ItemViewModel(item);
		Helper.Doc.Items.Insert(index, item);
		ItemList.Insert(index, view);
		SelectedItem = view;
	}

	private void DeleteItem()
	{
		if(SelectedItem == null)
			return;

		var item = SelectedItem; //引用项,下列操作中SelectedItem会被更改
		var index = ItemList.IndexOf(item);
		ItemList.Remove(item);
		Helper.Doc.Items.Remove(item.Core);
		if(index >= ItemList.Count)
		{
			index = ItemList.Count - 1;
		}

		SelectedItem = index >= 0 ? ItemList[index] : null;
	}

	private void MoveItem(bool isUp)
	{
		if(SelectedItem == null)
			return;

		int oldIndex = ItemList.IndexOf(SelectedItem);
		int newIndex = isUp ? oldIndex - 1 : oldIndex + 1;
		if(newIndex < 0 || newIndex >= ItemList.Count)
			return;

		var move = Helper.Doc.Items[oldIndex];
		Helper.Doc.Items.Remove(move);
		Helper.Doc.Items.Insert(newIndex, move);
		ItemList.Move(oldIndex, newIndex);
	}
}
